import { any } from "../core/logic";
import { Engine } from "../Engine";
import { Geometry } from "./Geometry";
import { process } from "../process/worker/process";
/**
 * 点状几何体。
 * @class
 * @memberof w.geometry
 */
class PointGeometry extends Geometry {
  /**
   * 创建材质
   * @constructor
   * @param {*} opts
   * @param {string} opts.name 【可选】名称。
   */
  constructor(opts = {}, share) {
    let rawPosition = any(opts.position, new Float32Array([]));
    delete opts.position
    super({autoUpdate: false});
    this.type = "PointGeometry";
    this.geometryType = "PointGeometry";
    this._hash = "";
    // this.position = opts.position;
    this.rawPosition = rawPosition;
    this.rawColor = any(opts.color, new Float32Array([]));
    this.varySize = any(opts.varySize, false);
    let camera=Engine.instance.scene.getCamera();
    let cameraDistance = camera.trans.position.distanceTo(camera.at)
    this.pixelRatio = cameraDistance*2.309401076758503/camera.size[1];
    this.size = any(opts.size, [300, 300]);
    this.horizontalLocation = any(opts.horizontalLocation, 'center');
    this.verticalLocation = any(opts.verticalLocation, 'middle');
    this.locationOffset = [0,0];
    this.relativeShift =  any(opts.relativeShift, [0,0]);
    this.shape = any(opts.shape, 'rect');
    this.calcData = opts.calcData;
    this.processCallback = any(opts.callback , () => {})
    this.fillPosition();
  }

  set varySize(v){
    this._varySize = v;
    this.addConfigParam("pointSizeVarying", v);
    return this;
  }
  get varySize(){
      return this._varySize;
  }
  set size(v){
      this._size=v;
      this.addParam("pointSize");
      return this;
  }
  get size(){
      return this._size;
  }
  set horizontalLocation(v){
      this._horizontalLocation=v;
      return this;
  }
  get horizontalLocation(){
      return this._horizontalLocation;
  }
  set verticalLocation(v){
      this._verticalLocation=v;
      return this;
  }
  get verticalLocation(){
      return this._verticalLocation;
  }
  set pointNormal(v){
      this._pointNormal=v;
      this.addParam("pointNormal");
      return this;
  }
  get pointNormal(){
      return this._pointNormal;
  }
  set relativeShift(v){
      if(!v) {
          v = [this.locationOffset[0], this.locationOffset[1]];
      } else {
          v = [v[0] + this.locationOffset[0], v[1] + this.locationOffset[1]];
      }
      this._relativeShift = v;
      this.addParam("relativeShift");
      return this;
  }
  get relativeShift(){
      return this._relativeShift;
  }
  set locationOffset(v){
      this._locationOffset=v;
      if(this.relativeShift) {
          this.relativeShift = this.relativeShift;
      }
      
      return this;
  }
  get locationOffset(){
      return this._locationOffset;
  }
  getPoints() {
    let noRepeatPoints = [];
    for (var j = 0; j < this.rawPosition.length; j += 3) {
        if(!(noRepeatPoints[noRepeatPoints.length - 1] && this.comparePoint(noRepeatPoints[noRepeatPoints.length - 1] ,[this.rawPosition[j], this.rawPosition[j+1], this.rawPosition[j+2]]))) {
            noRepeatPoints.push([this.rawPosition[j], this.rawPosition[j+1], this.rawPosition[j+2]])
        }
    }
    return noRepeatPoints;
}
  fillPosition(){
      let points = this.getPoints();
      this.noRepeatPoints = points;
      if(this.calcData) {
          let  {
              positions,
              indices_array,
              directions,
              uvs,
              colors,
              locationOffset
          } = this.calcData;
          this.autoUpdate = false;
          this.indices = indices_array;
          this.position = positions;
          this.locationOffset = locationOffset;
          this.pointNormal = directions;
          this.texCood0 = uvs;
          if(colors.length) {
              this.color = colors;
          }
          this.autoUpdate = true;
          this.update();
          this.processCallback(this.calcData);
      } else {
          process({
              type:"point",
              back: this.back,
              points,
              color: this.rawColor, 
              size: this.size,
              horizontalLocation: this.horizontalLocation,
              verticalLocation: this.verticalLocation,
              shape: this.shape
          },(message)=>{
              let  {
                  positions,
                  indices_array,
                  directions,
                  uvs,
                  colors,
                  locationOffset
              } = message.data;
              this.autoUpdate = false;
              this.indices = indices_array;
              this.position = positions;
              this.locationOffset = locationOffset;
              this.pointNormal = directions;
              this.texCood0 = uvs;
              if(colors.length) {
              //     let ColorCom = this.get('Color');
              //     ColorCom.size = 0;
                  this.color = colors;
              }
              this.autoUpdate = true;
              this.update();
              this.processCallback(message.data);
          })
      }
      
  }
  comparePoint(a, b) {
      if(!a || !b) return false;
      return (
          a[0] === b[0] &&
          a[1] === b[1] &&
          a[2] === b[2]
      )
  }
  toGPU() {
    if (this.has("pointSize")) {
      let data = [...this.size];
      if(this.varySize) {
          data = data.map(item => item*this.pixelRatio);
      }
      this.bufferToGPU(new Float32Array(data), 'pointSize', GPUShaderStage.VERTEX);
    }
    if (this.has("pointNormal")) {
      this.initVertex(this.pointNormal, "pointNormal", 3);
    }
    if (this.has("relativeShift")) {
      let data = [...this.relativeShift];
      if(this.varySize) {
          data = data.map(item => item*this.pixelRatio);
      }
      this.bufferToGPU(new Float32Array(data), 'relativeShift', GPUShaderStage.VERTEX);
    }
    super.toGPU();
  }
    

  
  
}

export { PointGeometry };
